//! # OpenTelemetry 增强追踪模块
//!
//! 提供完全兼容 OpenTelemetry 标准的分布式追踪功能，包括：
//! * OpenTelemetry Span 和 Trace 标准
//! * 多种导出器支持（Jaeger、Zipkin、OTLP）
//! * 上下文传播和采样策略
//! * 高性能批量导出

use crate::{DistributedTracer, TraceSpan, TracingResult, TracingError, SpanLog, TraceStatistics, TraceExportFormat};
use async_trait::async_trait;
use rustcloud_core::{ServiceResult, ServiceError};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::sync::{RwLock, mpsc};
use tracing::{debug, info, warn, error};
use uuid::Uuid;

/// OpenTelemetry 兼容的追踪配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OpenTelemetryConfig {
    /// 服务名称
    pub service_name: String,
    /// 服务版本
    pub service_version: String,
    /// 采样率 (0.0-1.0)
    pub sampling_rate: f64,
    /// 批量导出配置
    pub batch_config: BatchConfig,
    /// 资源属性
    pub resource_attributes: HashMap<String, String>,
    /// 是否启用
    pub enabled: bool,
    /// 最大span数量
    pub max_spans: usize,
    /// Span TTL
    pub span_ttl: Duration,
}

/// 批量导出配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatchConfig {
    /// 最大批量大小
    pub max_batch_size: usize,
    /// 导出超时时间
    pub export_timeout: Duration,
    /// 批量导出间隔
    pub export_interval: Duration,
    /// 队列最大大小
    pub max_queue_size: usize,
}

impl Default for OpenTelemetryConfig {
    fn default() -> Self {
        Self {
            service_name: "rustcloud-service".to_string(),
            service_version: "1.0.0".to_string(),
            sampling_rate: 1.0, // 100% 采样
            batch_config: BatchConfig::default(),
            resource_attributes: HashMap::new(),
            enabled: true,
            max_spans: 100000,
            span_ttl: Duration::from_secs(3600), // 1小时
        }
    }
}

impl Default for BatchConfig {
    fn default() -> Self {
        Self {
            max_batch_size: 512,
            export_timeout: Duration::from_secs(30),
            export_interval: Duration::from_secs(5),
            max_queue_size: 2048,
        }
    }
}

/// OpenTelemetry Span 上下文
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpanContext {
    /// Trace ID (128-bit)
    pub trace_id: String,
    /// Span ID (64-bit)
    pub span_id: String,
    /// 追踪标志
    pub trace_flags: u8,
    /// 追踪状态
    pub trace_state: String,
    /// 是否远程
    pub is_remote: bool,
}

impl SpanContext {
    /// 生成新的根上下文
    pub fn new_root() -> Self {
        Self {
            trace_id: generate_trace_id(),
            span_id: generate_span_id(),
            trace_flags: 1, // SAMPLED
            trace_state: String::new(),
            is_remote: false,
        }
    }

    /// 生成子上下文
    pub fn new_child(&self) -> Self {
        Self {
            trace_id: self.trace_id.clone(),
            span_id: generate_span_id(),
            trace_flags: self.trace_flags,
            trace_state: self.trace_state.clone(),
            is_remote: false,
        }
    }

    /// 检查是否被采样
    pub fn is_sampled(&self) -> bool {
        self.trace_flags & 0x01 != 0
    }

    /// 设置采样标志
    pub fn set_sampled(&mut self, sampled: bool) {
        if sampled {
            self.trace_flags |= 0x01;
        } else {
            self.trace_flags &= !0x01;
        }
    }
}

/// OpenTelemetry Span
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OtelSpan {
    /// Span 上下文
    pub context: SpanContext,
    /// 父 Span 上下文
    pub parent_context: Option<SpanContext>,
    /// 操作名称
    pub name: String,
    /// Span 类型
    pub kind: SpanKind,
    /// 开始时间
    pub start_time: SystemTime,
    /// 结束时间
    pub end_time: Option<SystemTime>,
    /// 属性
    pub attributes: HashMap<String, AttributeValue>,
    /// 事件
    pub events: Vec<SpanEvent>,
    /// 链接
    pub links: Vec<SpanLink>,
    /// 状态
    pub status: SpanStatus,
    /// 资源
    pub resource: Resource,
}

/// Span 类型
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum SpanKind {
    /// 内部 Span
    Internal,
    /// 服务器 Span
    Server,
    /// 客户端 Span  
    Client,
    /// 生产者 Span
    Producer,
    /// 消费者 Span
    Consumer,
}

/// 属性值
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum AttributeValue {
    String(String),
    Bool(bool),
    Int(i64),
    Double(f64),
    StringArray(Vec<String>),
    BoolArray(Vec<bool>),
    IntArray(Vec<i64>),
    DoubleArray(Vec<f64>),
}

/// Span 事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpanEvent {
    /// 事件时间
    pub time: SystemTime,
    /// 事件名称
    pub name: String,
    /// 事件属性
    pub attributes: HashMap<String, AttributeValue>,
}

/// Span 链接
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpanLink {
    /// 链接的 Span 上下文
    pub context: SpanContext,
    /// 链接属性
    pub attributes: HashMap<String, AttributeValue>,
}

/// Span 状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SpanStatus {
    /// 状态码
    pub code: StatusCode,
    /// 状态消息
    pub message: String,
}

/// 状态码
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StatusCode {
    /// 未设置
    Unset,
    /// 正常
    Ok,
    /// 错误
    Error,
}

/// 资源信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
    /// 资源属性
    pub attributes: HashMap<String, AttributeValue>,
}

/// OpenTelemetry 增强追踪器
pub struct EnhancedOpenTelemetryTracer {
    config: OpenTelemetryConfig,
    active_spans: Arc<RwLock<HashMap<String, OtelSpan>>>,
    span_exporter: Arc<dyn SpanExporter>,
    batch_processor: Option<mpsc::Sender<OtelSpan>>,
    sampler: Arc<dyn Sampler>,
    resource: Resource,
    statistics: Arc<RwLock<TraceStatistics>>,
}

/// Span 导出器接口
#[async_trait]
pub trait SpanExporter: Send + Sync {
    /// 导出 spans
    async fn export(&self, spans: Vec<OtelSpan>) -> ServiceResult<()>;
    
    /// 关闭导出器
    async fn shutdown(&self) -> ServiceResult<()>;
    
    /// 导出器名称
    fn name(&self) -> &str;
}

/// 采样器接口
pub trait Sampler: Send + Sync {
    /// 采样决策
    fn should_sample(&self, context: &SpanContext, trace_id: &str, name: &str, kind: SpanKind, attributes: &HashMap<String, AttributeValue>, links: &[SpanLink]) -> SamplingResult;
    
    /// 获取描述
    fn description(&self) -> String;
}

/// 采样结果
#[derive(Debug, Clone)]
pub struct SamplingResult {
    /// 是否采样
    pub decision: SamplingDecision,
    /// 附加属性
    pub attributes: HashMap<String, AttributeValue>,
    /// 追踪状态
    pub trace_state: String,
}

/// 采样决策
#[derive(Debug, Clone, PartialEq)]
pub enum SamplingDecision {
    /// 不采样
    Drop,
    /// 仅记录
    RecordOnly,
    /// 记录并采样
    RecordAndSample,
}

impl EnhancedOpenTelemetryTracer {
    /// 创建新的 OpenTelemetry 追踪器
    pub fn new(config: OpenTelemetryConfig, exporter: Arc<dyn SpanExporter>) -> Self {
        let mut resource_attributes = config.resource_attributes.clone();
        resource_attributes.insert("service.name".to_string(), AttributeValue::String(config.service_name.clone()));
        resource_attributes.insert("service.version".to_string(), AttributeValue::String(config.service_version.clone()));
        
        let resource = Resource {
            attributes: resource_attributes,
        };

        let sampler = Arc::new(TraceIdRatioBasedSampler::new(config.sampling_rate));

        Self {
            config,
            active_spans: Arc::new(RwLock::new(HashMap::new())),
            span_exporter: exporter,
            batch_processor: None,
            sampler,
            resource,
            statistics: Arc::new(RwLock::new(TraceStatistics {
                total_spans: 0,
                active_spans: 0,
                finished_spans: 0,
                avg_span_duration_ms: 0.0,
                sampling_rate: config.sampling_rate,
            })),
        }
    }

    /// 启动批量处理器
    pub async fn start_batch_processor(&mut self) -> ServiceResult<()> {
        let (tx, mut rx) = mpsc::channel::<OtelSpan>(self.config.batch_config.max_queue_size);
        
        let exporter = self.span_exporter.clone();
        let batch_config = self.config.batch_config.clone();
        
        tokio::spawn(async move {
            let mut batch = Vec::with_capacity(batch_config.max_batch_size);
            let mut interval = tokio::time::interval(batch_config.export_interval);
            
            loop {
                tokio::select! {
                    // 接收新的 span
                    span = rx.recv() => {
                        match span {
                            Some(span) => {
                                batch.push(span);
                                
                                // 如果批量达到最大大小，立即导出
                                if batch.len() >= batch_config.max_batch_size {
                                    if !batch.is_empty() {
                                        if let Err(e) = exporter.export(batch.clone()).await {
                                            error!("Failed to export span batch: {}", e);
                                        }
                                        batch.clear();
                                    }
                                }
                            }
                            None => {
                                // 通道关闭，导出剩余的 spans
                                if !batch.is_empty() {
                                    if let Err(e) = exporter.export(batch).await {
                                        error!("Failed to export final span batch: {}", e);
                                    }
                                }
                                break;
                            }
                        }
                    }
                    
                    // 定期导出
                    _ = interval.tick() => {
                        if !batch.is_empty() {
                            if let Err(e) = exporter.export(batch.clone()).await {
                                error!("Failed to export span batch on interval: {}", e);
                            }
                            batch.clear();
                        }
                    }
                }
            }
        });

        self.batch_processor = Some(tx);
        info!("Started OpenTelemetry batch processor");
        Ok(())
    }

    /// 开始新的 Span
    pub async fn start_span_with_context(&self, name: &str, context: Option<SpanContext>, kind: SpanKind) -> ServiceResult<OtelSpan> {
        if !self.config.enabled {
            return Err(ServiceError::TracingError("Tracing is disabled".to_string()));
        }

        let span_context = match context {
            Some(parent_ctx) => parent_ctx.new_child(),
            None => SpanContext::new_root(),
        };

        // 采样决策
        let sampling_result = self.sampler.should_sample(
            &span_context,
            &span_context.trace_id,
            name,
            kind.clone(),
            &HashMap::new(),
            &[]
        );

        let mut span_context = span_context;
        span_context.set_sampled(sampling_result.decision == SamplingDecision::RecordAndSample);

        let span = OtelSpan {
            context: span_context,
            parent_context: context,
            name: name.to_string(),
            kind,
            start_time: SystemTime::now(),
            end_time: None,
            attributes: sampling_result.attributes,
            events: Vec::new(),
            links: Vec::new(),
            status: SpanStatus {
                code: StatusCode::Unset,
                message: String::new(),
            },
            resource: self.resource.clone(),
        };

        // 添加到活跃 spans
        let span_id = span.context.span_id.clone();
        self.active_spans.write().await.insert(span_id, span.clone());

        // 更新统计信息
        let mut stats = self.statistics.write().await;
        stats.total_spans += 1;
        stats.active_spans = self.active_spans.read().await.len() as u64;

        debug!("Started span: {} ({})", name, span.context.span_id);
        Ok(span)
    }

    /// 结束 Span
    pub async fn end_span(&self, span: &mut OtelSpan) -> ServiceResult<()> {
        if span.end_time.is_some() {
            return Err(ServiceError::TracingError("Span already ended".to_string()));
        }

        span.end_time = Some(SystemTime::now());

        // 从活跃 spans 中移除
        self.active_spans.write().await.remove(&span.context.span_id);

        // 如果采样，发送到批量处理器
        if span.context.is_sampled() {
            if let Some(ref processor) = self.batch_processor {
                if let Err(e) = processor.send(span.clone()).await {
                    warn!("Failed to send span to batch processor: {}", e);
                }
            }
        }

        // 更新统计信息
        let mut stats = self.statistics.write().await;
        stats.finished_spans += 1;
        stats.active_spans = self.active_spans.read().await.len() as u64;

        debug!("Ended span: {} ({})", span.name, span.context.span_id);
        Ok(())
    }

    /// 添加属性
    pub fn set_attribute(&self, span: &mut OtelSpan, key: String, value: AttributeValue) {
        span.attributes.insert(key, value);
    }

    /// 添加事件
    pub fn add_event(&self, span: &mut OtelSpan, name: String, attributes: HashMap<String, AttributeValue>) {
        span.events.push(SpanEvent {
            time: SystemTime::now(),
            name,
            attributes,
        });
    }

    /// 设置状态
    pub fn set_status(&self, span: &mut OtelSpan, code: StatusCode, message: String) {
        span.status = SpanStatus { code, message };
    }

    /// 获取统计信息
    pub async fn get_statistics(&self) -> TraceStatistics {
        self.statistics.read().await.clone()
    }

    /// 关闭追踪器
    pub async fn shutdown(&self) -> ServiceResult<()> {
        // 关闭批量处理器
        if let Some(processor) = &self.batch_processor {
            // 通道会在所有发送者被丢弃时自动关闭
        }

        // 关闭导出器
        self.span_exporter.shutdown().await?;

        info!("OpenTelemetry tracer shutdown complete");
        Ok(())
    }
}

/// 基于 TraceID 的比率采样器
pub struct TraceIdRatioBasedSampler {
    sampling_rate: f64,
}

impl TraceIdRatioBasedSampler {
    pub fn new(sampling_rate: f64) -> Self {
        Self {
            sampling_rate: sampling_rate.clamp(0.0, 1.0),
        }
    }
}

impl Sampler for TraceIdRatioBasedSampler {
    fn should_sample(&self, context: &SpanContext, trace_id: &str, _name: &str, _kind: SpanKind, _attributes: &HashMap<String, AttributeValue>, _links: &[SpanLink]) -> SamplingResult {
        // 使用 trace_id 的哈希值进行一致性采样
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};
        
        let mut hasher = DefaultHasher::new();
        trace_id.hash(&mut hasher);
        let hash_value = hasher.finish();
        
        // 将哈希值转换为 0.0-1.0 的概率
        let probability = (hash_value as f64) / (u64::MAX as f64);
        
        let decision = if probability < self.sampling_rate {
            SamplingDecision::RecordAndSample
        } else {
            SamplingDecision::Drop
        };

        SamplingResult {
            decision,
            attributes: HashMap::new(),
            trace_state: context.trace_state.clone(),
        }
    }

    fn description(&self) -> String {
        format!("TraceIdRatioBasedSampler{{{}}}", self.sampling_rate)
    }
}

/// Jaeger 导出器
pub struct JaegerExporter {
    endpoint: String,
    service_name: String,
    client: reqwest::Client,
}

impl JaegerExporter {
    pub fn new(endpoint: String, service_name: String) -> Self {
        Self {
            endpoint,
            service_name,
            client: reqwest::Client::new(),
        }
    }
}

#[async_trait]
impl SpanExporter for JaegerExporter {
    async fn export(&self, spans: Vec<OtelSpan>) -> ServiceResult<()> {
        if spans.is_empty() {
            return Ok(());
        }

        let jaeger_traces = convert_to_jaeger_format(spans, &self.service_name);
        
        match self.client
            .post(&format!("{}/api/traces", self.endpoint))
            .json(&jaeger_traces)
            .send()
            .await
        {
            Ok(response) => {
                if response.status().is_success() {
                    debug!("Successfully exported {} spans to Jaeger", jaeger_traces.len());
                    Ok(())
                } else {
                    Err(ServiceError::TracingError(format!("Jaeger export failed with status: {}", response.status())))
                }
            }
            Err(e) => Err(ServiceError::TracingError(format!("Failed to send spans to Jaeger: {}", e)))
        }
    }

    async fn shutdown(&self) -> ServiceResult<()> {
        debug!("Jaeger exporter shutdown");
        Ok(())
    }

    fn name(&self) -> &str {
        "jaeger"
    }
}

/// Console 导出器（用于调试）
pub struct ConsoleExporter {
    pretty_print: bool,
}

impl ConsoleExporter {
    pub fn new(pretty_print: bool) -> Self {
        Self { pretty_print }
    }
}

#[async_trait]
impl SpanExporter for ConsoleExporter {
    async fn export(&self, spans: Vec<OtelSpan>) -> ServiceResult<()> {
        for span in spans {
            if self.pretty_print {
                println!("🔍 Span: {} ({})", span.name, span.context.span_id);
                println!("   📍 Trace: {}", span.context.trace_id);
                if let Some(parent) = &span.parent_context {
                    println!("   👨‍👩‍👧‍👦 Parent: {}", parent.span_id);
                }
                println!("   ⏱️  Duration: {:?}", 
                    span.end_time.and_then(|end| 
                        end.duration_since(span.start_time).ok()
                    ).unwrap_or_default()
                );
                if !span.attributes.is_empty() {
                    println!("   🏷️  Attributes: {:?}", span.attributes);
                }
                if !span.events.is_empty() {
                    println!("   📝 Events: {}", span.events.len());
                }
                println!();
            } else {
                println!("{:?}", span);
            }
        }
        Ok(())
    }

    async fn shutdown(&self) -> ServiceResult<()> {
        println!("Console exporter shutdown");
        Ok(())
    }

    fn name(&self) -> &str {
        "console"
    }
}

// 辅助函数

fn generate_trace_id() -> String {
    format!("{:032x}", Uuid::new_v4().as_u128())
}

fn generate_span_id() -> String {
    format!("{:016x}", Uuid::new_v4().as_u128() & 0xffffffffffffffff)
}

fn convert_to_jaeger_format(spans: Vec<OtelSpan>, service_name: &str) -> serde_json::Value {
    // 简化的 Jaeger 格式转换
    // 实际实现需要完整的 Jaeger Thrift 格式
    serde_json::json!({
        "data": spans.into_iter().map(|span| {
            serde_json::json!({
                "traceID": span.context.trace_id,
                "spanID": span.context.span_id,
                "parentSpanID": span.parent_context.as_ref().map(|p| &p.span_id),
                "operationName": span.name,
                "startTime": span.start_time.duration_since(UNIX_EPOCH).unwrap_or_default().as_micros(),
                "duration": span.end_time.and_then(|end| 
                    end.duration_since(span.start_time).ok()
                ).unwrap_or_default().as_micros(),
                "tags": span.attributes,
                "process": {
                    "serviceName": service_name,
                    "tags": span.resource.attributes
                }
            })
        }).collect::<Vec<_>>()
    })
}

/// 兼容 DistributedTracer trait 的适配器
pub struct OpenTelemetryAdapter {
    tracer: Arc<EnhancedOpenTelemetryTracer>,
}

impl OpenTelemetryAdapter {
    pub fn new(tracer: EnhancedOpenTelemetryTracer) -> Self {
        Self {
            tracer: Arc::new(tracer),
        }
    }
}

#[async_trait]
impl DistributedTracer for OpenTelemetryAdapter {
    async fn start_span(&self, operation_name: &str, parent_span: Option<&TraceSpan>) -> TracingResult<TraceSpan> {
        let parent_context = parent_span.map(|p| SpanContext {
            trace_id: p.trace_id.clone(),
            span_id: p.span_id.clone(),
            trace_flags: 1,
            trace_state: String::new(),
            is_remote: false,
        });

        let otel_span = self.tracer.start_span_with_context(operation_name, parent_context, SpanKind::Internal).await
            .map_err(|e| Box::new(TracingError::InvalidOperation(e.to_string())) as Box<dyn std::error::Error + Send + Sync>)?;

        // 转换为 TraceSpan
        Ok(TraceSpan {
            trace_id: otel_span.context.trace_id,
            span_id: otel_span.context.span_id,
            parent_span_id: otel_span.parent_context.map(|p| p.span_id),
            operation_name: otel_span.name,
            start_time: otel_span.start_time,
            finish_time: otel_span.end_time,
            tags: otel_span.attributes.into_iter().map(|(k, v)| (k, format!("{:?}", v))).collect(),
            logs: otel_span.events.into_iter().map(|e| SpanLog {
                timestamp: e.time,
                message: e.name,
                fields: e.attributes.into_iter().map(|(k, v)| (k, format!("{:?}", v))).collect(),
            }).collect(),
        })
    }

    async fn finish_span(&self, span: &mut TraceSpan) -> TracingResult<()> {
        // 从活跃 spans 中查找对应的 OtelSpan
        let active_spans = self.tracer.active_spans.read().await;
        if let Some(mut otel_span) = active_spans.get(&span.span_id).cloned() {
            drop(active_spans);
            
            // 更新 span 信息
            span.finish_time = Some(SystemTime::now());
            
            self.tracer.end_span(&mut otel_span).await
                .map_err(|e| Box::new(TracingError::InvalidOperation(e.to_string())) as Box<dyn std::error::Error + Send + Sync>)?;
        }

        Ok(())
    }

    async fn add_span_tag(&self, span: &mut TraceSpan, key: &str, value: &str) -> TracingResult<()> {
        span.tags.insert(key.to_string(), value.to_string());
        
        // 同时更新 OtelSpan
        let mut active_spans = self.tracer.active_spans.write().await;
        if let Some(otel_span) = active_spans.get_mut(&span.span_id) {
            self.tracer.set_attribute(otel_span, key.to_string(), AttributeValue::String(value.to_string()));
        }

        Ok(())
    }

    async fn add_span_log(&self, span: &mut TraceSpan, message: &str, fields: &HashMap<String, String>) -> TracingResult<()> {
        let log = SpanLog {
            timestamp: SystemTime::now(),
            message: message.to_string(),
            fields: fields.clone(),
        };
        span.logs.push(log);

        // 同时更新 OtelSpan
        let mut active_spans = self.tracer.active_spans.write().await;
        if let Some(otel_span) = active_spans.get_mut(&span.span_id) {
            let attributes = fields.iter()
                .map(|(k, v)| (k.clone(), AttributeValue::String(v.clone())))
                .collect();
            self.tracer.add_event(otel_span, message.to_string(), attributes);
        }

        Ok(())
    }

    async fn export_traces(&self, _format: TraceExportFormat) -> TracingResult<String> {
        // 这里可以导出当前的追踪数据
        let stats = self.tracer.get_statistics().await;
        Ok(serde_json::to_string_pretty(&stats).unwrap())
    }

    async fn get_trace_statistics(&self) -> TracingResult<TraceStatistics> {
        Ok(self.tracer.get_statistics().await)
    }
}